﻿using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SZHelperCore.GMSM
{
    public class SM2Utils
    {
        private byte[] publicKey;
        private byte[] privateKey;
        public SM2Utils(string pubK,string prik)
        {
            publicKey= Hex.Decode(pubK);
            privateKey = Hex.Decode(prik);
        }

        public static void GenerateKeyPair(out string publicKey, out string privateKey)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");
            KeyGenerationParameters parameters = new ECKeyGenerationParameters(new ECDomainParameters(curve), new SecureRandom());

            // 创建 SM2 密钥对生成器
            ECKeyPairGenerator generator = new ECKeyPairGenerator();
            generator.Init(parameters);

            // 创建密钥对
            var keyPair = generator.GenerateKeyPair();

            // 私钥
            ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters)keyPair.Private;
            //privateKey = Base64.ToBase64String(privateKeyParameters.D.ToByteArrayUnsigned());
            privateKey = Encoding.UTF8.GetString(Hex.Encode(privateKeyParameters.D.ToByteArrayUnsigned())).ToUpper();


            // 公钥
            ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters)keyPair.Public;
            //publicKey = Base64.ToBase64String(publicKeyParameters.Q.GetEncoded());
            publicKey = Encoding.UTF8.GetString(Hex.Encode(publicKeyParameters.Q.GetEncoded())).ToUpper();
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string Encrypt(string data)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");

            ECPoint q = curve.Curve.DecodePoint(publicKey);
            ECDomainParameters domain = new ECDomainParameters(curve);
            ECPublicKeyParameters pubk = new ECPublicKeyParameters("EC", q, domain);

            // 创建SM2加密器
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.Init(true, new ParametersWithRandom(pubk, new SecureRandom()));

            // 将原始数据转换为字节数组
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);

            // 执行加密操作
            byte[] encryptedData = sm2Engine.ProcessBlock(dataBytes, 0, dataBytes.Length);

            // 将加密结果转换为 Base64 字符串
            return Encoding.UTF8.GetString(Hex.Encode(encryptedData));
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string Decrypt(string data)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");

            ECDomainParameters domain = new ECDomainParameters(curve);
            //BigInteger d = new BigInteger(1, Encoding.UTF8.GetBytes(privateKey));
            BigInteger d = new BigInteger(1, privateKey);
            ECPrivateKeyParameters prik = new ECPrivateKeyParameters(d, domain);

            // 创建SM2加密器
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.Init(false, prik);

            byte[] encryptedData = Hex.Decode(Encoding.UTF8.GetBytes(data));

            // 执行解密操作
            byte[] decryptedData = sm2Engine.ProcessBlock(encryptedData, 0, encryptedData.Length);

            // 将解密结果转换为字符串
            return Encoding.UTF8.GetString(decryptedData);
        }
    }
}
